package org.geekbang.projects.rest;


import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.geekbang.projects.rest.client.DefaultVariantListBuilder;
import org.geekbang.projects.rest.core.DefaultResponseBuilder;
import org.geekbang.projects.rest.core.DefaultUriBuilder;

import javax.ws.rs.core.*;
import javax.ws.rs.ext.RuntimeDelegate;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class HttpRuntimeDelegate extends RuntimeDelegate {



    private  final static Map<Class , HeaderDelegate> HEADER_DELEGATE_MAPPING = new HashMap<>();


    @Override
    public UriBuilder createUriBuilder() {
        return new DefaultUriBuilder();
    }

    @Override
    public Response.ResponseBuilder createResponseBuilder() {
        return new DefaultResponseBuilder();
    }

    @Override
    public Variant.VariantListBuilder createVariantListBuilder() {
        return new DefaultVariantListBuilder();
    }

    @Override
    public <T> T createEndpoint(Application application, Class<T> endpointType) throws IllegalArgumentException, UnsupportedOperationException {
        return null;
    }

    @Override
    public <T> HeaderDelegate<T> createHeaderDelegate(Class<T> type) throws IllegalArgumentException {
        return HEADER_DELEGATE_MAPPING.get(type);
    }

    @Override
    public Link.Builder createLinkBuilder() {
        return null;
    }


    static {
        HEADER_DELEGATE_MAPPING.put(Cookie.class , CookieHeaderDelegate.INSTANCE);
        HEADER_DELEGATE_MAPPING.put(NewCookie.class , NewCookieHeaderDelegate.INSTANCE);
        HEADER_DELEGATE_MAPPING.put(MediaType.class , MediaTypeHeaderDelegate.INSTANCE);
    }

    /**
     * cookie 头委托处理器
     */
    public static class CookieHeaderDelegate<T extends Cookie> implements HeaderDelegate<Cookie>{

        public static final CookieHeaderDelegate INSTANCE = new CookieHeaderDelegate();

        @Override
        public Cookie fromString(String value) {
            if (StringUtils.isEmpty(value)){
                return null;
            }
            String[] split = value.split("=");
            return new Cookie(split[0] , split[1]);
        }

        @Override
        public String toString(Cookie value) {
            return value.getName() + "=" + value.getValue();
        }
    }

    /**
     * new cookie 头委托处理器
     */
    public static class NewCookieHeaderDelegate extends CookieHeaderDelegate<NewCookie>{
        public static final NewCookieHeaderDelegate INSTANCE = new NewCookieHeaderDelegate();
    }


    /**
     * MediaType 头的委托器
     */
    public static class MediaTypeHeaderDelegate implements HeaderDelegate<MediaType> {

        public static final MediaTypeHeaderDelegate INSTANCE = new MediaTypeHeaderDelegate();


        @Override
        public MediaType fromString(String value) {
            if (StringUtils.isEmpty(value)){
                return null;
            }
            String[] split = value.split(";");
            String types = split[0];
            String[] split1 = types.split("/");
            Map<String, String> params = new HashMap<>();
            if (split.length > 1) {
                for (int i = 1, l = split.length; i < l; i++) {
                    String[] param = split[i].split("=");
                    params.put(param[0] , param[1]);
                }
            }
            return new MediaType(split1[0] , split1[1] , params );
        }

        @Override
        public String toString(MediaType value) {
            StringBuilder sb = new StringBuilder();
            sb.append(value.getType());
            sb.append("/");
            sb.append(value.getSubtype());
            Map<String, String> parameters = value.getParameters();
            if (!MapUtils.isEmpty(parameters)){
                sb.append(";");
                sb.append(parameters.entrySet()
                        .stream().map(item -> item.getKey() + "=" + item.getValue()).collect(Collectors.joining(";")));
            }
            return sb.toString();
        }
    }
}
